<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>

    // 递归实现深拷贝
    function clone(obj) {
      if (typeof obj !== 'object' || obj === null)
        return null
      // Array.isArray
      let cloneObj = Array.isArray(obj) ? [] : {}
      for (let key in obj)
        // 兼容数组和对象，所以使用obj[key] === array[index]
        if (typeof obj[key] === 'object' || typeof obj[key] === 'array')
          cloneObj[key] = clone(obj[key])
        else
          cloneObj[key] = obj[key];
      return cloneObj;
    }

    let obj = {
      yy: 'yy',
      fqm: {
        fqm: 'fqmyysjjd'
      }
    }
    let obj_ = clone(obj)


    // 使用JSON.parser(JSON.stringfy(obj)) //  也可以实现深拷贝

    // 但是JSON.parser(JSON.stringfy(obj))的局限性：
    // 会忽略 undefined
    // 会忽略 symbol
    // 不能序列化函数
    // 不能解决循环引用的对象

    // 以上会忽略
    let obj3 = {
      name: 'jack',
      age: undefined,
      sex: Symbol('male'),
      play: function () { }
    }
    let objCopy = JSON.parse(JSON.stringify(obj3))
    console.log(objCopy)    // {name: 'jack'}



    // 使用展开运算运算符，只是一层深拷贝，对于嵌套的引用类型式浅拷贝
    // 对于第一层属性直接替换，比如上述对象的fqm属性，不访问原对象堆数据的值，直接把obj1.fqm替换，不会影响,
    // 相当于对于fqm栈里的地址换了指向,所以原来fqm指向的对象不会改变

    let obj1 = { ...obj }
    let obj2 = Object.assign({}, obj)   // 使用assign合并一样

  </script>

</body>

</html>